"""
模块名称：example_aht20.py
作者：李雪康
创建时间：2025 - 11 - 04
最后修改时间：2025 - 11 - 04
功能描述：AHT20 温湿度传感器驱动示例程序
"""


import utime
from machine import I2C


AHT20_CALIBRATION_CMD       = b"\xE1"   # Initialization command
AHT20_START_MEASURMENT_CMD  = b"\xAC"   # Trigger measurement
AHT20_RESET_CMD             = b"\xBA"   # reset
AHT20_STATUS_CMD            = b"\x71"    # get status byte


class I2CIOWrapper(object):
    """IIC 接口适配器"""

    class I2CReadError(Exception):
        pass

    class I2CWriteError(Exception):
        pass

    def __init__(self, i2c, slaveaddr):
        if not isinstance(i2c, I2C):
            raise TypeError("`i2c` should be machine.I2C type")
        self.__i2c = i2c
        self.__slaveaddr = slaveaddr

    def __str__(self):
        return "{}(0x{:X}) device".format(type(self).__name__, self.__slaveaddr)
    
    def read(self, reg, size=1, delay=0):
        """读取寄存器值"""
        if size <= 0:
            raise ValueError("`size` should be greater than 0")
        data = bytearray(size)
        if self.__i2c.read(self.__slaveaddr, reg, len(reg), data, size, delay) != 0:
            raise self.I2CReadError("{} read {} failed".format(self, reg))
        return data

    def write(self, reg, data):
        """写寄存器值"""
        if not isinstance(data, (bytearray, bytes)):
            raise TypeError("`data` should be bytearray or bytes")
        if self.__i2c.write(self.__slaveaddr, reg, len(reg), data, len(data)) != 0:
            raise self.I2CWriteError("{} write {}, {} failed".format(self, reg, data))



class Aht20(I2CIOWrapper):

    def __init__(self, i2c, slaveaddr=0x38):
        super().__init__(i2c, slaveaddr)

    def getStatus(self):
        """获取传感器状态"""
        return self.read(AHT20_STATUS_CMD, 1)[0]

    def init(self):
        """传感器初始化"""
        self.write(AHT20_CALIBRATION_CMD, b"\x08\x00")
        utime.sleep_ms(10)

    def reset(self):
        """传感器重置"""
        self.write(AHT20_RESET_CMD, b'')
        utime.sleep_ms(20)  # at last 20ms

    def trigger_measure(self):
        """触发测量，返回值为 (湿度，温度)"""
        self.write(AHT20_START_MEASURMENT_CMD, b"\x33\x00")
        utime.sleep_ms(80)  # at last delay 80ms
        r_data = self.read(b'', size=6)
        if r_data[0] & (1 << 7):
            print("Conversion has error")
            return None
        data = r_data[1:6]
        humidity = (data[0] << 12) | (data[1] << 4) | ((data[2] & 0xF0) >> 4)
        humidity = (humidity / (1 << 20)) * 100.0
        temperature = ((data[2] & 0xf) << 16) | (data[3] << 8) | data[4]
        temperature = (temperature * 200.0 / (1 << 20)) - 50
        return humidity, temperature


if __name__ == "__main__":
    i2c_obj = I2C(I2C.I2C1, I2C.STANDARD_MODE)  # 实例化 IIC 对象，通道0
    aht_obj = Aht20(i2c_obj)  # 实例化 Aht20 对象
    aht_obj.init()  # 传感器初始化
    
    # 测试，间隔 1s 循环读取并打印出湿度和温度
    while True:
        humidity, temperature = aht_obj.trigger_measure()
        print("read humidity: {:.2f}%, temperature: {:.2f}℃".format(humidity, temperature))
        utime.sleep(1)
